package busuanzi.module;

import busuanzi.storage.MongoClient;
import busuanzi.util.Sugars;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.googlecode.concurrentlinkedhashmap.Weighers;
import com.mongodb.Function;
import org.bson.Document;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import static busuanzi.storage.MongoClient.s;
import static sardine.Sardine.get;

/**
 * Auth: bruce-sha
 * Date: 2015/4/29
 */
public abstract class Statistics {

    static ConcurrentMap<String, AtomicInteger> counters = new ConcurrentLinkedHashMap
            .Builder<String, AtomicInteger>()
            .maximumWeightedCapacity(100)
            .weigher(Weighers.singleton())
            .build();

    static final ExecutorService executor = Executors.newFixedThreadPool(3);


    static void asynCount() {
        executor.submit(new Runnable() {
            @Override
            public void run() {
                String today = LocalDate.now().toString();
                AtomicInteger counter = new AtomicInteger();
                counters.putIfAbsent(today, counter);
                counter = counters.getOrDefault(today, counter);
                counter.getAndIncrement();
            }
        });
    }

    public static void run() {

        get("/stats", "application/json", (request, response) -> {
            return MongoClient.bath("busuanzi/busuan", busuans -> {
                List<Stats> re = busuans.find(s("{path: '_pv'}")).sort(s("{lastModified: -1}"))
                        .map(new Function<Document, Stats>() {
                            @Override
                            public Stats apply(Document d) {
                                return new Stats(
                                        d.getString("host"),
                                        d.getInteger("count"),
                                        d.getDate("lastModified"));
                            }
                        }).into(new LinkedList<Stats>());
                re.add(0, new Stats("total", re.size(), new Date()));
                return re;
            });
        }, Sugars.HtmlJsonTransformer);


        get("/stats2", (request, response) -> {
            return new TreeMap<String, AtomicInteger>(counters);
        }, Sugars.HtmlJsonTransformer);


        get("/nocors", (request, response) -> {
            return "nocors";
        });

        get("/cors", (request, response) -> {

            response.header("Access-Control-Allow-Credentials", "true");
            response.header("Access-Control-Allow-Origin", "*");
            response.header("Access-Control-Allow-Origin", "http://localhost:9527");
            response.header("Access-Control-Allow-Headers", "Origin, Accept-Language, Accept-Encoding, X-Forwarded-For, Connection, Accept, User-Agent, Host, Referer, Cookie, Content-Type, Cache-Control, If-Modified-Since, *");
            response.header("Access-Control-Expose-Headers", "Date");

            return "cors";
        });


//        get("/stats/detail", "application/json", (request, response) -> {
//            return RedisPool.bath((jedis) -> {
//                List<Stats> re = Lists.newArrayList();
//                // 获取所有站点
//                Set<String> sites = jedis.keys("*");
//
//                for (String site : sites) {
//
//                    final Stats stats = new Stats();
//                    stats.site = site;
//
//                    Set<Tuple> pages = jedis.zrangeWithScores(site, 0, -1);
//
//                    final List<Map> pagesModel = Lists.newArrayList();
//
//                    for (Tuple pt : pages) {
//
//
//                        String page = pt.getElement();
//                        double counter = pt.getScore();
//
//                        pagesModel.add(Collections.singletonMap(page, counter));
//                    }
//
//                    stats.pages = pagesModel;
//                    stats.site = site;
//                    re.add(stats);
//                }
//
//                return re;
//            });
//        }, HtmlJsonTransformer);
    }

    public static class Stats/* implements Comparable<Stats>*/ {
        String host;
        int count;
        String lastModified;

        public Stats(String host, int count, Date lastModified) {
            this.host = host;
            this.count = count;
            if (lastModified == null) {
                Calendar ca = Calendar.getInstance();
                ca.set(2000, 1, 1);
                lastModified = ca.getTime();
            }
            this.lastModified = simpleFormat.format(lastModified);
        }

        public String getHost() {
            return host;
        }

        public int getCount() {
            return count;
        }

        public String getLastModified() {
            return lastModified;
        }

       /* public int compareTo(Stats o) {
            int t = o.lastModified.compareTo(lastModified);
            if (t == 0)
                return o.host.compareTo(host);
            else
                return t;
        }*/

//        @Override
//        public String toString() {
//            return String.format("%s   '%s':%s", lastModified, host, count);
//        }

        final SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    }

}
